package com.xmall.product.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmall.define.constants.CommonProperties;
import com.xmall.define.dict.LogStatusEnum;
import com.xmall.define.dto.log.RetryLogDto;
import com.xmall.define.request.sys.RetryLogListPageQueryRequest;
import com.xmall.product.define.constants.ProductConstants;
import com.xmall.product.define.constants.ProductProperties;
import com.xmall.product.entity.StockDeductRetryLog;
import com.xmall.product.mapper.StockDeductRetryLogMapper;
import com.xmall.product.service.ISkuInfoService;
import com.xmall.product.service.IStockDeductRetryLogService;
import com.xmall.product.utils.ConvertUtils;
import com.xmall.timer.handler.IRetryLogTaskHandler;
import com.xmall.utils.TimerUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存扣减日志 服务实现类
 * </p>
 *
 * @author xmall
 * @since 2023-11-21
 */
@Service
public class StockDeductRetryLogServiceImpl extends ServiceImpl<StockDeductRetryLogMapper, StockDeductRetryLog> implements IStockDeductRetryLogService, IRetryLogTaskHandler {

    @Resource
    private ISkuInfoService skuInfoService;

    @Resource
    private CommonProperties commonProperties;

    @Resource
    private ProductProperties productProperties;

    /**
     * 新增数据保存，重复数据不保存
     */
    @Override
    public void saveDuplicate(Long orderId) {
        StockDeductRetryLog log = new StockDeductRetryLog();
        log.setOrderId(orderId);
        log.setCreateTime(new Date());
        log.setNextRetryTime(DateUtil.offsetSecond(new Date(), commonProperties.getLogRetryIntervalSecondsList().get(0)));
        this.baseMapper.saveDuplicate(log);
    }

    /**
     * 完成
     */
    @Override
    public Boolean complete(Long orderId) {
        return this.update(
                new StockDeductRetryLog(LogStatusEnum.PROCESSED.getStatus()),
                new QueryWrapper<StockDeductRetryLog>().eq("order_id", orderId).eq("log_status", LogStatusEnum.PROCESSING.getStatus()));
    }

    @Override
    public String key() {
        return ProductConstants.TimerTask.STOCK_DEDUCT_LOG_RETRY_TASK;
    }

    @Override
    public String name() {
        return "库存扣减日志任务";
    }

    @Override
    public String cron() {
        return productProperties.getStockDeductLogRetryCron();
    }

    @Override
    public void execute() {
        TimerUtils.retryExecute(commonProperties, this, retryLog -> skuInfoService.stockDeduct(retryLog.getOrderId()));
    }

    /**
     * 是否有异常
     */
    @Override
    public Boolean hasException() {
        return this.count(new QueryWrapper<StockDeductRetryLog>().gt("retry_count", 0).eq("log_status", LogStatusEnum.PROCESSING.getStatus())) > 0;
    }

    @Override
    public Page<RetryLogDto> retryListPage(RetryLogListPageQueryRequest request) {
        Page<RetryLogDto> result = new Page<>();

        QueryWrapper query = new QueryWrapper();
        query.orderByDesc("retry_count");
        query.orderByDesc("create_time");

        Page<StockDeductRetryLog> page = this.page(new Page(request.getPage(), request.getPageSize()), query);

        BeanUtils.copyProperties(page, result);

        List<RetryLogDto> retryLogDtoList = page.getRecords().stream().map(retryLog -> {
            RetryLogDto retryLogDto = ConvertUtils.RetryLogModule.INSTANCE.toDtoFromStockDeduct(retryLog);
            retryLogDto.setMeta(retryLog);
            return retryLogDto;
        }).collect(Collectors.toList());

        result.setRecords(retryLogDtoList);
        return result;
    }
}
